﻿
Imports osi.root.constants
Imports osi.root.connector
Imports osi.root.procedure
Imports osi.root.formation
Imports osi.root.delegates
Imports osi.root.utils
Imports osi.service.argument
Imports osi.service.convertor
Imports osi.service.selector

Public Module _dependent_allocator
    Private Function wait_device_timeout_ms(ByVal p As var, ByVal name As String) As Int64
        assert(Not p Is Nothing)
        Return p(strcat(name, "-timeout-ms")).to_int64(npos)
    End Function

    Public Function dependent_allocate(Of T, PT, RT)(ByVal name As String,
                                                     ByVal c As Func(Of T, PT, pointer(Of RT), event_comb),
                                                     ByVal p As PT,
                                                     ByVal r As pointer(Of RT),
                                                     Optional ByVal wait_device_timeout_ms As Int64 = npos) _
                                                    As event_comb
        assert(Not c Is Nothing)
        Dim ec As event_comb = Nothing
        Dim i As pointer(Of T) = Nothing
        Return New event_comb(Function() As Boolean
                                  i = New pointer(Of T)()
                                  ec = device_manager.get(name, i, wait_device_timeout_ms)
                                  Return waitfor(ec) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  If ec.end_result() Then
                                      ec = c(+i, p, r)
                                      Return waitfor(ec) AndAlso
                                             goto_next()
                                  Else
                                      Return False
                                  End If
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         goto_end()
                              End Function)
    End Function

    Public Function dependent_allocator(Of T, PT, RT)(ByVal name As String,
                                                      ByVal c As Func(Of T, PT, pointer(Of RT), event_comb),
                                                      Optional ByVal wait_device_timeout_ms As Int64 = npos) _
                                                     As allocator(Of RT, PT)
        Return make_allocator(Function(p As PT, r As pointer(Of RT)) As event_comb
                                  Return dependent_allocate(name, c, p, r, wait_device_timeout_ms)
                              End Function)
    End Function

    Public Function dependent_allocator(Of T, RT)(ByVal name As String,
                                                  ByVal c As Func(Of T, var, pointer(Of RT), event_comb)) _
                                                 As allocator(Of RT, var)
        Dim ec As event_comb = Nothing
        Return make_allocator(Function(p As var, r As pointer(Of RT)) As event_comb
                                  Return New event_comb(Function() As Boolean
                                                            If p Is Nothing Then
                                                                Return False
                                                            Else
                                                                ec = dependent_allocate(p(name),
                                                                                        c,
                                                                                        p,
                                                                                        r,
                                                                                        wait_device_timeout_ms(p, name))
                                                                Return waitfor(ec) AndAlso
                                                                       goto_next()
                                                            End If
                                                        End Function,
                                                        Function() As Boolean
                                                            Return ec.end_result() AndAlso
                                                                   goto_end()
                                                        End Function)
                              End Function)
    End Function

    Public Function dependent_allocate(Of T1, T2, PT, RT)(ByVal n1 As String,
                                                          ByVal n2 As String,
                                                          ByVal c As Func(Of T1, T2, PT, pointer(Of RT), event_comb),
                                                          ByVal p As PT,
                                                          ByVal r As pointer(Of RT),
                                                          Optional ByVal wdtms1 As Int64 = npos,
                                                          Optional ByVal wdtms2 As Int64 = npos) As event_comb
        assert(Not c Is Nothing)
        Dim ec As event_comb = Nothing
        Dim ec2 As event_comb = Nothing
        Dim i As pointer(Of T1) = Nothing
        Dim j As pointer(Of T2) = Nothing
        Return New event_comb(Function() As Boolean
                                  i = New pointer(Of T1)()
                                  j = New pointer(Of T2)()
                                  ec = device_manager.get(n1, i, wdtms1)
                                  ec2 = device_manager.get(n2, j, wdtms2)
                                  Return waitfor(ec, ec2) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  ec = c(+i, +j, p, r)
                                  Return waitfor(ec) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         goto_end()
                              End Function)
    End Function

    Public Function dependent_allocator(Of T1, T2, PT, RT)(ByVal n1 As String,
                                                           ByVal n2 As String,
                                                           ByVal c As Func(Of T1, T2, PT, pointer(Of RT), event_comb),
                                                           Optional ByVal wdtms1 As Int64 = npos,
                                                           Optional ByVal wdtms2 As Int64 = npos) _
                                                          As allocator(Of RT, PT)
        Return make_allocator(Function(p As PT, r As pointer(Of RT)) As event_comb
                                  Return dependent_allocate(n1, n2, c, p, r, wdtms1, wdtms2)
                              End Function)
    End Function

    Public Function dependent_allocator(Of T1, T2, RT)(ByVal n1 As String,
                                                       ByVal n2 As String,
                                                       ByVal c As Func(Of T1, T2, var, pointer(Of RT), event_comb)) _
                                                      As allocator(Of RT, var)
        Dim ec As event_comb = Nothing
        Return make_allocator(Function(p As var, r As pointer(Of RT)) As event_comb
                                  Return New event_comb(Function() As Boolean
                                                            If p Is Nothing Then
                                                                Return False
                                                            Else
                                                                ec = dependent_allocate(p(n1),
                                                                                        p(n2),
                                                                                        c,
                                                                                        p,
                                                                                        r,
                                                                                        wait_device_timeout_ms(p, n1),
                                                                                        wait_device_timeout_ms(p, n2))
                                                                Return waitfor(ec) AndAlso
                                                                       goto_next()
                                                            End If
                                                        End Function,
                                                        Function() As Boolean
                                                            Return ec.end_result() AndAlso
                                                                   goto_end()
                                                        End Function)
                              End Function)
    End Function

    Public Function dependent_allocate(Of T1, T2, T3, PT, RT)(ByVal n1 As String,
                                                              ByVal n2 As String,
                                                              ByVal n3 As String,
                                                              ByVal c As _func(Of T1, 
                                                                                  T2, 
                                                                                  T3, 
                                                                                  PT, 
                                                                                  pointer(Of RT), 
                                                                                  event_comb),
                                                              ByVal p As PT,
                                                              ByVal r As pointer(Of RT),
                                                              Optional ByVal wdtms1 As Int64 = npos,
                                                              Optional ByVal wdtms2 As Int64 = npos,
                                                              Optional ByVal wdtms3 As Int64 = npos) As event_comb
        assert(Not c Is Nothing)
        Dim ec As event_comb = Nothing
        Dim ec2 As event_comb = Nothing
        Dim ec3 As event_comb = Nothing
        Dim i As pointer(Of T1) = Nothing
        Dim j As pointer(Of T2) = Nothing
        Dim k As pointer(Of T3) = Nothing
        Return New event_comb(Function() As Boolean
                                  i = New pointer(Of T1)()
                                  j = New pointer(Of T2)()
                                  k = New pointer(Of T3)()
                                  ec = device_manager.get(n1, i, wdtms1)
                                  ec2 = device_manager.get(n2, j, wdtms2)
                                  ec3 = device_manager.get(n3, k, wdtms3)
                                  Return waitfor(ec, ec2, ec3) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  ec = c(+i, +j, +k, p, r)
                                  Return waitfor(ec) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         goto_end()
                              End Function)
    End Function

    Public Function dependent_allocator(Of T1, T2, T3, PT, RT)(ByVal n1 As String,
                                                               ByVal n2 As String,
                                                               ByVal n3 As String,
                                                               ByVal c As _func(Of T1, 
                                                                                   T2, 
                                                                                   T3, 
                                                                                   PT, 
                                                                                   pointer(Of RT), 
                                                                                   event_comb),
                                                               Optional ByVal wdtms1 As Int64 = npos,
                                                               Optional ByVal wdtms2 As Int64 = npos,
                                                               Optional ByVal wdtms3 As Int64 = npos) _
                                                              As allocator(Of RT, PT)
        Return make_allocator(Function(p As PT, r As pointer(Of RT)) As event_comb
                                  Return dependent_allocate(n1, n2, n3, c, p, r, wdtms1, wdtms2, wdtms3)
                              End Function)
    End Function

    Public Function dependent_allocator(Of T1, T2, T3, RT)(ByVal n1 As String,
                                                           ByVal n2 As String,
                                                           ByVal n3 As String,
                                                           ByVal c As _func(Of T1, 
                                                                               T2, 
                                                                               T3, 
                                                                               var, 
                                                                               pointer(Of RT), 
                                                                               event_comb)) _
                                                          As allocator(Of RT, var)
        Dim ec As event_comb = Nothing
        Return make_allocator(Function(p As var, r As pointer(Of RT)) As event_comb
                                  Return New event_comb(Function() As Boolean
                                                            If p Is Nothing Then
                                                                Return False
                                                            Else
                                                                ec = dependent_allocate(p(n1),
                                                                                        p(n2),
                                                                                        p(n3),
                                                                                        c,
                                                                                        p,
                                                                                        r,
                                                                                        wait_device_timeout_ms(p, n1),
                                                                                        wait_device_timeout_ms(p, n2),
                                                                                        wait_device_timeout_ms(p, n3))
                                                                Return waitfor(ec) AndAlso
                                                                       goto_next()
                                                            End If
                                                        End Function,
                                                        Function() As Boolean
                                                            Return ec.end_result() AndAlso
                                                                   goto_end()
                                                        End Function)
                              End Function)
    End Function

    Public Function dependent_allocate(Of T1, T2, T3, T4, PT, RT)(ByVal n1 As String,
                                                                  ByVal n2 As String,
                                                                  ByVal n3 As String,
                                                                  ByVal n4 As String,
                                                                  ByVal c As _func(Of T1, 
                                                                                      T2, 
                                                                                      T3, 
                                                                                      T4, 
                                                                                      PT, 
                                                                                      pointer(Of RT), 
                                                                                      event_comb),
                                                                  ByVal p As PT,
                                                                  ByVal r As pointer(Of RT),
                                                                  Optional ByVal wdtms1 As Int64 = npos,
                                                                  Optional ByVal wdtms2 As Int64 = npos,
                                                                  Optional ByVal wdtms3 As Int64 = npos,
                                                                  Optional ByVal wdtms4 As Int64 = npos) As event_comb
        assert(Not c Is Nothing)
        Dim ec As event_comb = Nothing
        Dim ec2 As event_comb = Nothing
        Dim ec3 As event_comb = Nothing
        Dim ec4 As event_comb = Nothing
        Dim i As pointer(Of T1) = Nothing
        Dim j As pointer(Of T2) = Nothing
        Dim k As pointer(Of T3) = Nothing
        Dim l As pointer(Of T4) = Nothing
        Return New event_comb(Function() As Boolean
                                  i = New pointer(Of T1)()
                                  j = New pointer(Of T2)()
                                  k = New pointer(Of T3)()
                                  l = New pointer(Of T4)()
                                  ec = device_manager.get(n1, i, wdtms1)
                                  ec2 = device_manager.get(n2, j, wdtms2)
                                  ec3 = device_manager.get(n3, k, wdtms3)
                                  ec4 = device_manager.get(n4, l, wdtms4)
                                  Return waitfor(ec, ec2, ec3, ec4) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  ec = c(+i, +j, +k, +l, p, r)
                                  Return waitfor(ec) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         goto_end()
                              End Function)
    End Function

    Public Function dependent_allocator(Of T1, T2, T3, T4, PT, RT)(ByVal n1 As String,
                                                                   ByVal n2 As String,
                                                                   ByVal n3 As String,
                                                                   ByVal n4 As String,
                                                                   ByVal c As _func(Of T1, 
                                                                                       T2, 
                                                                                       T3, 
                                                                                       T4, 
                                                                                       PT, 
                                                                                       pointer(Of RT), 
                                                                                       event_comb),
                                                                   Optional ByVal wdtms1 As Int64 = npos,
                                                                   Optional ByVal wdtms2 As Int64 = npos,
                                                                   Optional ByVal wdtms3 As Int64 = npos,
                                                                   Optional ByVal wdtms4 As Int64 = npos) _
                                                                  As allocator(Of RT, PT)
        Return make_allocator(Function(p As PT, r As pointer(Of RT)) As event_comb
                                  Return dependent_allocate(n1, n2, n3, n4, c, p, r, wdtms1, wdtms2, wdtms3, wdtms4)
                              End Function)
    End Function

    Public Function dependent_allocator(Of T1, T2, T3, T4, RT)(ByVal n1 As String,
                                                               ByVal n2 As String,
                                                               ByVal n3 As String,
                                                               ByVal n4 As String,
                                                               ByVal c As _func(Of T1, 
                                                                                   T2, 
                                                                                   T3, 
                                                                                   T4, 
                                                                                   var, 
                                                                                   pointer(Of RT), 
                                                                                   event_comb)) _
                                                              As allocator(Of RT, var)
        Dim ec As event_comb = Nothing
        Return make_allocator(Function(p As var, r As pointer(Of RT)) As event_comb
                                  Return New event_comb(Function() As Boolean
                                                            If p Is Nothing Then
                                                                Return False
                                                            Else
                                                                ec = dependent_allocate(p(n1),
                                                                                        p(n2),
                                                                                        p(n3),
                                                                                        p(n4),
                                                                                        c,
                                                                                        p,
                                                                                        r,
                                                                                        wait_device_timeout_ms(p, n1),
                                                                                        wait_device_timeout_ms(p, n2),
                                                                                        wait_device_timeout_ms(p, n3),
                                                                                        wait_device_timeout_ms(p, n4))
                                                                Return waitfor(ec) AndAlso
                                                                       goto_next()
                                                            End If
                                                        End Function,
                                                        Function() As Boolean
                                                            Return ec.end_result() AndAlso
                                                                   goto_end()
                                                        End Function)
                              End Function)
    End Function
End Module
